﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Linq;
using System.Windows;
using PSE.Deployment.ConfigurationManager.Controls;
using PSE.Deployment.SetupBase.Configuration;
using PSE.Deployment.SetupBase.Configuration.Actions;
using PSE.Deployment.SetupBase.Parameter.Enums;
using PSE.Deployment.Util;
using System.IO;

namespace PSE.Deployment.SetupBase.UI
{
    public partial class CheckPreviouslyVersion : BaseWizardWindow
    {
        #region Propriedades
        public ObservableCollection<InvalidProgram> InvalidPrograms { get; set; }
        #endregion

        #region Construtor
        public CheckPreviouslyVersion()
        {
            this.InitializeComponent();
            this.ConfirmOnClosing = false;

            InvalidPrograms = new ObservableCollection<InvalidProgram>();

            this.btnCancel.Click += new RoutedEventHandler(btnCancel_Click);
            this.btnRefresh.Click += new RoutedEventHandler(btnRefresh_Click);
            this.btnRemoveAll.Click += new RoutedEventHandler(btnRemoveAll_Click);

            this.DataContext = this;

            //atualizar o texto da tela com o ID do sistema
            txtSystemName.Text = SetupMainFactory.GetInstance().Configuration.SystemInfo.Id;
            txtSystemName1.Text = SetupMainFactory.GetInstance().Configuration.SystemInfo.Id;

            this.AllowNext = false;
        }
        #endregion

        #region Evento do Botão Remover Todos
        private void btnRemoveAll_Click(object sender, RoutedEventArgs e)
        {
            UninstallServices();

            KillProcesses();

            CheckAllowNext();
        }
        #endregion

        #region Evento do Botão Atualizar
        private void btnRefresh_Click(object sender, RoutedEventArgs e)
        {
            CheckInstalledPrograms(!SetupMainFactory.GetInstance().Parameter.IsInstalled);

            CheckAllowNext();
        }
        #endregion

        #region Evento do Botão Cancelar
        private void btnCancel_Click(object sender, RoutedEventArgs e)
        {
            this.Close();
        }
        #endregion

        #region Método Allow Next
        private void CheckAllowNext()
        {
            this.AllowNext = (InvalidPrograms.Count == 0);
        }
        #endregion

        #region Check Installed Programs

        public void CheckInstalledPrograms(bool checkProcess)
        {
            IEnumerable<Group> Groups = SetupMainFactory.GetInstance().Configuration.SystemInfo.Groups.SelectDeep(g => g.SubGroups).SelectDeep(g => g.Dependencies).Distinct(new GroupComparer());

            InvalidPrograms.Clear();

            CheckInstalledService("Bovespa WCF Services Hoster", "Bovespa WCF Services Hoster");

            CheckInstalledService("BM&FBOVESPA WCF Services Hoster", "BvmfServiceHoster");

            CheckWindowsService(Groups);

            if (checkProcess)
            {
                CheckProcess(Groups);
            }
        }

        #endregion

        #region Unistall Services

        private void KillProcesses()
        {
            for (int i = InvalidPrograms.Count - 1; i >= 0; i--)
            {
                if (PSE.Deployment.Util.Windows.KillProcess(InvalidPrograms[i].DisplayName) != 0)
                {
                    InvalidPrograms.RemoveAt(i);
                }
            }
        }

        private void UninstallServices()
        {
            for (int i = InvalidPrograms.Count - 1; i >= 0; i--)
            {
                try
                {
                    PSE.Deployment.Util.WindowsService.ServiceInfo serviceInfo = PSE.Deployment.Util.WindowsService.GetServiceInfo(InvalidPrograms[i].ServiceName);

                    if (serviceInfo != null)
                    {
                        string message;

                        if (PSE.Deployment.Util.WindowsService.UninstallService(InvalidPrograms[i].ServiceName, serviceInfo.binaryPathName.Replace("\"", ""), out message))
                        {
                            if (InvalidPrograms[i].ServiceName == SetupMainFactory.GetInstance().HosterName)
                            {
                                DeleteHosterFile();
                            }

                            InvalidPrograms.RemoveAt(i);
                        }
                        else
                        {
                            string error = string.Format("Ocorreu um erro ao tentar desinstalar o serviço {0} \n Verifique o log na pasta '{1}' para maiores detalhes.", InvalidPrograms[i].DisplayName, SetupMainFactory.GetInstance().LogPath);
                            ConfigurationMessageBox.Show(error, "Atenção", ConfigurationMessageBoxButton.Ok, ConfigurationMessageBoxImage.Error);
                            SetupMainFactory.GetInstance().WriteStepLog(error + Environment.NewLine + message);
                        }
                    }
                }
                catch (Exception ex)
                {
                    ConfigurationMessageBox.Show(string.Format("Ocorreu um erro ao tentar para o serviço {0}", InvalidPrograms[i].DisplayName) + Environment.NewLine + "Erro: " + ex.Message, "Atenção", ConfigurationMessageBoxButton.Ok, ConfigurationMessageBoxImage.Error);
                }
            }
        }

        private void DeleteHosterFile()
        {
            string hosterFile = string.Format(@"{0}\BMFBOVESPA\ServiceHoster\user.config", PSE.Deployment.Util.Windows.GetFolderPath(PSE.Deployment.Util.Windows.SpecialFolder.ApplicationData));

            if (System.IO.File.Exists(hosterFile))
                System.IO.File.Delete(hosterFile);

            if (Directory.Exists(Path.GetDirectoryName(hosterFile)))
                PSE.Deployment.Util.File.DeleteEmptyDirectories(SetupMainFactory.GetInstance().Parameter.InstallationPath, Path.GetDirectoryName(hosterFile));
        }

        #endregion

        #region Check Process / WindowsService

        private void CheckInstalledService(string displayName, string serviceName)
        {
            PSE.Deployment.Util.WindowsService.ServiceInfo serviceInfo = PSE.Deployment.Util.WindowsService.GetServiceInfo(serviceName);

            if (serviceInfo != null)
            {
                InvalidPrograms.Add(new InvalidProgram() { DisplayName = displayName, ServiceName = serviceName, FilePath = serviceInfo.binaryPathName.Replace("\"", "") });
            }
        }

        private void CheckWindowsService(IEnumerable<Group> Groups)
        {
            List<InstallWindowsService> servicesConfiguration = (from g in Groups
                                                                 from a in g.Actions
                                                                 where a is InstallWindowsService
                                                                 select (InstallWindowsService)a).Distinct(new WindowsServiceComparer()).ToList();

            foreach (InstallWindowsService serviceConfiguration in servicesConfiguration)
            {
                foreach (PSE.Deployment.SetupBase.Configuration.WindowsService windowsService in serviceConfiguration.Services)
                {
                    PSE.Deployment.Util.WindowsService.ServiceInfo serviceInfo = PSE.Deployment.Util.WindowsService.GetServiceInfo(windowsService.ServiceName);

                    if (serviceInfo != null)
                    {
                        string filePath = SetupMainFactory.GetInstance().Parameter.InstallationPath + windowsService.ServiceFile.Destination + windowsService.ServiceFile.FileName;

                        if (SetupMainFactory.GetInstance().Parameter.IsInstalled)
                        {
                            if (SetupMainFactory.GetInstance().Parameter.SetupMode == SetupMode.Install || SetupMainFactory.GetInstance().Parameter.SetupMode == SetupMode.Uninstall)
                            {
                                if (filePath != serviceInfo.binaryPathName.Replace("\"", ""))
                                {
                                    InvalidPrograms.Add(new InvalidProgram() { DisplayName = windowsService.DisplayName, ServiceName = windowsService.ServiceName, FilePath = filePath });
                                }
                            }
                        }
                        else
                        {
                            InvalidPrograms.Add(new InvalidProgram() { DisplayName = windowsService.DisplayName, ServiceName = windowsService.ServiceName, FilePath = filePath });
                        }
                    }
                }
            }
        }

        private void CheckProcess(IEnumerable<Group> Groups)
        {
            List<string> files = new List<string>();

            List<PSE.Deployment.SetupBase.Configuration.ActionBase> aplications = (from g in Groups
                                                                                   from a in g.Actions
                                                                                   where a is PSE.Deployment.SetupBase.Configuration.Actions.Copy
                                                                                   select a).Distinct(new ActionComparer()).ToList();

            foreach (PSE.Deployment.SetupBase.Configuration.ActionBase action in aplications)
            {

                if (action is PSE.Deployment.SetupBase.Configuration.Actions.Copy)
                {
                    foreach (PSE.Deployment.SetupBase.Configuration.FolderInfo folderInfo in ((PSE.Deployment.SetupBase.Configuration.Actions.Copy)action).Folders)
                    {
                        string path = System.IO.Path.Combine(SetupMainFactory.GetInstance().Parameter.InstallationPath, folderInfo.Destination);

                        if (folderInfo.Files.Count == 0)
                        {
                            if (System.IO.Directory.Exists(path))
                                files.AddRange(System.IO.Directory.GetFiles(path, "*.exe", System.IO.SearchOption.AllDirectories));
                        }
                        else
                        {
                            foreach (string file in folderInfo.Files)
                            {
                                if (System.IO.Path.GetExtension(file).ToLower() == ".exe")
                                {
                                    files.Add(file);
                                }
                            }
                        }
                    }
                }
            }

            foreach (string file in files)
            {
                InvalidProgram invalidProgram = InvalidPrograms.ToList().Find(m => Path.GetFileNameWithoutExtension(m.FilePath) == Path.GetFileNameWithoutExtension(file));

                Process[] processList = Process.GetProcessesByName(Path.GetFileNameWithoutExtension(file));

                if (processList.Length > 0)
                {
                    if (invalidProgram == null)
                    {
                        InvalidPrograms.Add(new InvalidProgram() { DisplayName = Path.GetFileNameWithoutExtension(file), FilePath = file });
                    }
                }
            }
        }

        #endregion
    }

    public class InvalidProgram
    {
        public string DisplayName { get; set; }
        public string ServiceName { get; set; }
        public string Description { get; set; }
        public string FilePath { get; set; }
    }
}
